package com.shotgun.mycommon.webservice.aspect;

import com.alibaba.fastjson.JSON;
import com.shotgun.mycommon.webservice.util.MethodLogUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;


/**
 *
 * @desc 拦截方法的入参信息和返回信息
 */
@Aspect
@Configuration
public class MethodLogAop {
    private static final Logger log = LoggerFactory.getLogger(MethodLogAop.class);

    @Pointcut(value = "execution(* com.shotgun..*Controller.*(..))")
    private void controllerLog() {
    }

    @Pointcut(value = "execution(* com.shotgun..*Service.*(..))")
    private void serviceLog() {
    }


    @Around(value = "controllerLog() || serviceLog()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {

        // 获取拦截的方法名
        MethodSignature msig = (MethodSignature) joinPoint.getSignature();
        // 获取方法参数
        Object[] objectsArray = joinPoint.getArgs();

        // 纳秒时间戳
        long startNanoTime = System.nanoTime();

        String requestId = UUID.randomUUID().toString();
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        String requestURL = null;
        String method = null;
        if (attributes != null) {
            HttpServletRequest request = attributes.getRequest();
            requestURL = request.getRequestURL().toString();
            method = request.getMethod();
        }


        String params;
        try {
            params = JSON.toJSONString(objectsArray);
        } catch (Exception e) {
            log.warn("参数序列化失败: {}", e.getMessage());
            params = "参数序列化失败";
        }

        MethodLogUtils.logRequest(MethodLogUtils.INVOKE_SELF_STR, requestId, requestURL, method, msig.getDeclaringType().getSimpleName(), msig.getName(), params);

        // 执行方法
        Object resultObj = joinPoint.proceed();

        String result;
        try {
            result = JSON.toJSONString(resultObj);
        } catch (Exception e) {
            log.warn("返回结果序列化失败: {}", e.getMessage());
            result = "返回结果序列化失败";
        }

        MethodLogUtils.logResponse(MethodLogUtils.INVOKE_SELF_STR, requestId, requestURL, method, msig.getDeclaringType().getSimpleName(), msig.getName(), params,
                result, (System.nanoTime() - startNanoTime) / 1000000);

        return resultObj;
    }

}